<html>
<head>

<title>Groovy Goodness: Magic Package to Add Custom MetaClass</title>

<script language="javascript" src="scripts/shCore.js"></script> 
<script language="javascript" src="scripts/shLegacy.js"></script> 
<script language="javascript" src="scripts/shBrushJava.js"></script> 
<script language="javascript" src="scripts/shBrushXml.js"></script> 
<script language="javascript" src="scripts/shBrushJScript.js"></script> 
<script language="javascript" src="scripts/shBrushGroovy.js"></script> 
<script language="javascript" src="scripts/shBrushPlain.js"></script> 
<script language="javascript" src="scripts/shBrushBash.js"></script> 
 
<link href="styles/reset.css" rel="stylesheet" type="text/css" />
<link href="styles/shCore.css" rel="stylesheet" type="text/css" />
<link type="text/css" rel="stylesheet" href="styles/shThemeRDark.css"/>
<link href="styles/blog.css" rel="stylesheet" type="text/css" />

</head>
<body>

<a href="index.html">Back to index</a>

<h3 class="post-title">Groovy Goodness: Magic Package to Add Custom MetaClass</h3>

<div class="post">
<p>Groovy is very dynamic. We can add methods to classes at runtime that don't exist at compile time. We can add our own custom <code>MetaClass</code> at startup time of our application if we follow the <em>magic</em> package naming convention. The naming convention is <code>groovy.runtime.metaclass.[package].[class]MetaClass</code>. For example if we want to change the behavior of the <code>java.lang.String</code> class, then we must write a custom <code>MetaClass</code> with the package name <code>groovy.runtime.metaclass.java.lang</code> and class name <code>StringMetaClass</code>. We can do the same for classes we create ourselves. For example if we have a class <code>myapp.RunApp</code> than the custom metaclass implementation <code>RunAppMetaClass</code> would be in package <code>groovy.runtime.metaclass.myapp</code>.</p><p>Our custom <code>MetaClass</code> is extended from <code>DelegatingMetaClass</code> and besides the name of the class and the package we can write our code the way we want.</p><p>We must first compile the custom <code>MetaClass</code> and then we must put it in the classpath of the application code that is going to use the <code>MetaClass</code>.</p><pre class="brush:groovy">// File: StringMetaClass.groovy
package groovy.runtime.metaclass.java.lang

class StringMetaClass extends DelegatingMetaClass {

    StringMetaClass(MetaClass meta) {
        super(meta)
    }

    Object invokeMethod(Object object, String method, Object[] arguments) {
        if (method == 'hasGroovy') {
            object ==~ /.*[Gg]roovy.*/
        } else {
            super.invokeMethod object, method, arguments
        }
    }
}
</pre><p>The code that will use the delegating metaclass implementation:</p><pre class="brush:groovy">// File: StringDelegateSample.groovy

// Original methods are still invoked.
assert 'mrhaki'.toUpperCase() == 'MRHAKI'

// Invoke 'hasGroovy' method we added via the DelegatingMetaClass.
assert !'Java'.hasGroovy()
assert 'mrhaki loves Groovy'.hasGroovy()
assert 'Groovy'.toLowerCase().hasGroovy()
</pre><p>First we compile our <code>StringMetaClass</code>:<br /><code>$ groovyc StringMetaClass.groovy</code>.</p><p>Next we can run the <code>StringDelegateSample.groovy</code> file if we put the generated class file in our classpath:<br /><code>$ groovy -cp . StringDelegateSample</code></p><br /
</div>

<script language="javascript"> 
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
SyntaxHighlighter.defaults['first-line'] = 0;
SyntaxHighlighter.defaults['auto-links'] = false;
SyntaxHighlighter.all();
dp.SyntaxHighlighter.HighlightAll('code');
</script>

</body>
</html>